/*----------------------------------------------------------------------*
 *	CLASS:		Qt3SquareImpl
 *	Quantum Tic Tac Toe
 *	Copyright (c) 2005-2009 Novatia Labs, Inc.  All rights reserved.
 *----------------------------------------------------------------------*/

package com.novatialabs.qttt.engine.impl;

import com.novatialabs.qttt.engine.Qt3Player;
import com.novatialabs.qttt.engine.Qt3Square;

/**
 * Qt3SquareImpl provides information about the state of a particular
 * square in the game board.
 *
 * @Author	John Levine
 * @Author	Duane Gibson
 * @Author Friendly development resources cheerfully provided by Charles Phares.
 * @Author	$Author$
 * @Version	$Revision$
 */

public final class Qt3SquareImpl
    implements Qt3Square
{

   /**
    * The index in the state's tangle array of the root of this tangle.
    */
    private int		tangleIndex	= -1;

   /**
    * An array of flags that will be set to true for each move made in
    * this square.  To avoid the subscript math, the zero-element in the
    * array will be ignored.
    */
    private boolean[]	moveMap;

   /**
    * This is zero if no move has yet collapsed to this square,
    * otherwise this is the number (1-9) of the move that has collapsed
    * to this square.
    * Note also, between a move and its collapse, this may be set to the
    * stem move that has been forced into this square and will become
    * permanent when the collapse is completed.  The pending flag
    * indicates whether this is owning move is pending or permanent.
    */
    private int		owningMove;

   /**
    * A flag indicating whether the owning move is pending (a stem of the
    * entanglement that has been forced into this square regardless of
    * the collapse resolution) or permanent.
    */
    private boolean	pending;

   /*-------------------------------------------------------------------*
    *	CONSTRUCTOR:	Qt3SquareImpl()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Sun Jan  9 17:55:46 PST 2005
    *-------------------------------------------------------------------*/
   /**
    * Constructs a new, initial Qt3SquareImpl.
    */

    /*package*/ Qt3SquareImpl()
    {

	this.moveMap = new boolean[Qt3GameEngine.MAX_MOVES+1];

    } // Qt3SquareImpl()

   /*-------------------------------------------------------------------*
    *	METHOD:		cloneSquare()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Tue Jan 11 16:02:22 PST 2005
    *-------------------------------------------------------------------*/
   /**
    * Returns a clone of this square.
    */

    /*package*/ Qt3SquareImpl cloneSquare()
    {
	Qt3SquareImpl testTube = new Qt3SquareImpl();

	for ( int index = 1 ; index <= Qt3GameEngine.MAX_MOVES ; ++index ) {
	    testTube.moveMap[index] = this.moveMap[index];
	}

	testTube.owningMove  = this.owningMove;
	testTube.pending     = this.pending;
	testTube.tangleIndex = this.tangleIndex;

	return testTube;

    } // cloneSquare()

   /*-------------------------------------------------------------------*
    *	METHOD:		addMove()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Tue Jan 11 16:26:08 PST 2005
    *-------------------------------------------------------------------*/
   /**
    * Adds a move to this square.
    *
    * @param	moveNumber	number of the move to add.
    */

    /*package*/ void addMove(
	int	moveNumber
	)
    {

	this.moveMap[moveNumber] = true;

    } // addMove()

   /*-------------------------------------------------------------------*
    *	METHOD:		isMoveInSquare()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Tue Feb 15 17:25:34 PST 2005
    *-------------------------------------------------------------------*/
   /**
    * Returns whether the indicated move is in this square.
    *
    * @param	moveNum	number of the move. 
    */

    public boolean isMoveInSquare( int moveNum )
    {
	return this.moveMap[moveNum];
    } // isMoveInSquare()

   /*-------------------------------------------------------------------*
    *	METHOD:		getOwner()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Tue Jan 11 12:00:24 PST 2005
    *-------------------------------------------------------------------*/
   /**
    * Returns the player that owns this square, or null if no move has
    * yet been collapsed to this square.
    */

    public Qt3Player getOwner()
    {
	final int collapsingMove = this.owningMove;

	if ( (collapsingMove == 0) || (this.pending) ) {
	    return null;
	}

	return Qt3GameEngine.getPlayerForMove(collapsingMove);

    } // getOwner()

   /*-------------------------------------------------------------------*
    *	METHOD:		getOwningMove()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Tue Jan 11 12:03:24 PST 2005
    *-------------------------------------------------------------------*/
   /**
    * Returns the move number (1-9) that collapsed into this square
    * or 0 if no move has yet been collapsed to this square.
    */

    public int getOwningMove()
    {
	if ( this.pending ) {
	    return 0;
	}

	return this.owningMove;
    } // getOwningMove()

   /*-------------------------------------------------------------------*
    *	METHOD:		getPendingOwner()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Thu Mar  9 19:48:43 PST 2006
    *-------------------------------------------------------------------*/
   /**
    * Returns the player that will own this square when the collapse is
    * completed, or null if the move has not pushed a stem into this
    * square.
    */

    public Qt3Player getPendingOwner()
    {
	final int collapsingMove = this.owningMove;

	if ( collapsingMove == 0 ) {
	    return null;
	}

	return Qt3GameEngine.getPlayerForMove(collapsingMove);

    } // getPendingOwner()

   /*-------------------------------------------------------------------*
    *	METHOD:		getPendingOwningMove()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Thu Mar  9 19:50:02 PST 2006
    *-------------------------------------------------------------------*/
   /**
    * Returns the move number (1-9) that does (or will when the collapse
    * is complete) own this square or 0 if the game so far has not
    * collapsed or pushed a stem into this square.
    */

    public int getPendingOwningMove()
    {
	return this.owningMove;
    } // getPendingOwningMove()


   /*-------------------------------------------------------------------*
    *	METHOD:		finalizeMove()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Sun Jan 30 00:43:57 PST 2005
    *-------------------------------------------------------------------*/
   /**
    * Sets the move number (1-9) that collapsed into this square.
    *
    * @param	collapsingMove	the move number that collapsed into this
    *				square. 
    */

    /*package*/ void finalizeMove( final int collapsingMove )
    {
	/*assert((collapsingMove >= 1) && (collapsingMove <= 9));*/
	this.owningMove = collapsingMove;
	this.pending = false;
    } // finalizeMove()


   /*-------------------------------------------------------------------*
    *	METHOD:		recordPendingOwningMove()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Thu Mar  9 20:31:22 PST 2006
    *-------------------------------------------------------------------*/
   /**
    * Sets the move number (1-9) of the stem that will collapse into
    * this square.
    *
    * @param	collapsingMove	the move number that collapsed into this
    *				square. 
    */

    /*package*/ void recordPendingOwningMove( final int collapsingMove )
    {
	/*assert((collapsingMove >= 1) && (collapsingMove <= 9));*/
	this.owningMove = collapsingMove;
	this.pending = true;
    } // recordPendingOwningMove()

   /*-------------------------------------------------------------------*
    *	METHOD:		finalizeCollapse()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Thu Mar  9 20:18:58 PST 2006
    *-------------------------------------------------------------------*/
   /**
    * Indicates that the collapse is complete and any pending owner is
    * now permanent.
    */

    /*package*/ void finalizeCollapse()
    {
	this.pending = false;
    } // finalizeCollapse()

   /*-------------------------------------------------------------------*
    *	METHOD:		getTangleIndex()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Mon Jan 10 21:43:31 PST 2005
    *-------------------------------------------------------------------*/
   /**
    * Returns the index of the tangle of which this square is a part,
    * or -1 if this square is not in a tangle.
    */

    public int getTangleIndex()
    {
	return this.tangleIndex;
    } // getTangleIndex()

   /*-------------------------------------------------------------------*
    *	METHOD:		setTangleIndex()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Mon Jan 10 21:43:39 PST 2005
    *-------------------------------------------------------------------*/
   /**
    * Sets the tangle of which this square is a part.
    *
    * @param newTangle	tangle to set. 
    */

    /*package*/ void setTangleIndex(
	int	newTangle
	)
    {
	this.tangleIndex = newTangle;
    } // setTangleIndex()


} // class Qt3SquareImpl

